home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / ae.lha / ae / AE / ae-output.c < prev    next >
C/C++ Source or Header  |  1990-02-28  |  36KB  |  1,542 lines

  1. /* AE program profiling system.
  2.    Code to produce schemas and instrument assembly code.
  3.    Copyright (C) 1989, 1990 by James R. Larus (larus@cs.wisc.edu)
  4.  
  5.    AE and AEC are free software; you can redistribute it and/or modify it
  6.    under the terms of the GNU General Public License as published by the
  7.    Free Software Foundation; either version 1, or (at your option) any
  8.    later version.
  9.  
  10.    AE and AEC are distributed in the hope that it will be useful, but
  11.    WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.    General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with GNU CC; see the file COPYING.  If not, write to James R.
  17.    Larus, Computer Sciences Department, University of Wisconsin--Madison,
  18.    1210 West Dayton Street, Madison, WI 53706, USA or to the Free
  19.    Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21.  
  22. /* $Header: /var/home/larus/AE/AE/RCS/ae-output.c,v 2.2 90/02/14 09:20:01 larus Exp Locker: larus $ */
  23.  
  24.  
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include "config.h"
  28. #include "rtl.h"
  29. #include "basic-block.h"
  30. #include "flags.h"
  31. #include "regs.h"
  32. #include "ae.h"
  33. #include "ae-machine.h"
  34. #include "schema.h"
  35.  
  36.  
  37. void ae_after_block_end ();
  38. void ae_after_call_insn ();
  39. void ae_after_easy_insn ();
  40. void ae_after_impossible_insn ();
  41. void ae_after_load_insn ();
  42. void ae_after_store_insn ();
  43. void ae_before_block_end ();
  44. void ae_before_call_insn ();
  45. void ae_before_easy_insn ();
  46. void ae_before_impossible_insn ();
  47. void ae_before_load_insn ();
  48. void ae_before_store_insn ();
  49. void ae_block_start ();
  50. void ae_function_end ();
  51. void ae_function_start ();
  52. int asm_insn_size ();
  53. void block_end_cjump_schema ();
  54. void block_end_jump_schema ();
  55. void block_end_schema ();
  56. void block_start_schema ();
  57. void call_indirect_schema ();
  58. void call_schema ();
  59. void call_schema_str ();
  60. int cjump_target_p ();
  61. void compute_def_schema ();
  62. int condjump_p ();
  63. list defns_reaching_insn ();
  64. void edge_schema ();
  65. rtx find_block_head ();
  66. void find_mem_refs ();
  67. void flush_uneventful_insn ();
  68. void free_list ();
  69. void function_end_schema ();
  70. void function_start_schema ();
  71. rtx gen_rtx ();
  72. int get_frame_size ();
  73. int head_to_block_number ();
  74. int implicit_last_block ();
  75. void issue_address_event ();
  76. void issue_event ();
  77. void issue_event_space_check ();
  78. void issue_short_event ();
  79. void load_schema_int_offset ();
  80. void load_schema_reg_offset ();
  81. void load_symbol_schema ();
  82. void load_unknown_schema ();
  83. int multiway_jump_p ();
  84. rtx next_insn_or_label ();
  85. void note_stores ();
  86. void output_asm_insn ();
  87. void peek_ahead ();
  88. void process_block_start ();
  89. void process_insn_after ();
  90. void process_insn_before ();
  91. int record_fp ();
  92. void record_insn_effects ();
  93. int record_sp ();
  94. void rtx_arg_out ();
  95. char *rtx_op_out ();
  96. void save_store_dest ();
  97. void simple_def_schema ();
  98. int simplejump_p ();
  99. void store_schema_int_offset ();
  100. void store_schema_reg_offset ();
  101. void store_symbol_schema ();
  102. void store_unknown_schema ();
  103. int substring ();
  104. void symbol_def_schema ();
  105. void uneventful_schema ();
  106. void unknown_def_schema ();
  107.  
  108.  
  109. rtx *basic_block_end;
  110. rtx *basic_block_head;
  111.  
  112. extern aux_insn_info *insn_info; /* Information on instructions */
  113.  
  114. extern char record_reg_on_entry []; /* Non-zero => save register upon entry. */
  115.  
  116. extern FILE *asm_out_file;    /* Assembly output file. */
  117.  
  118. extern FILE *schema_out_file;    /* Schema output file. */
  119.  
  120. extern char *fun_name;        /* Name of function being processed. */
  121.  
  122.  
  123. /* Maintain a circular queue of the next MAX_PEEP instructions and
  124.    their patterns, so we can look ahead (LA) to account for the effects
  125.    of instructions deleted by peephole optimization. */
  126.  
  127. static rtx la_insn [MAX_PEEP];
  128.  
  129. static rtx la_pattern [MAX_PEEP];
  130.  
  131.  
  132. /* H points one position before first item in queue.  T points to the
  133.    last element in queue. */
  134.  
  135. static int la_h = 0, la_t = 0;
  136.  
  137.  
  138. /* Non-zero if the assembly code for an instruction is not yet output. */
  139.  
  140. static int before_insn_flg;
  141.  
  142.  
  143. /* Number of block being processed. */
  144.  
  145. static int block_no;
  146.  
  147.  
  148. /* Used to retrieve destination of store instruction via NOTE_STORE. */
  149.  
  150. static rtx store_dest;
  151.  
  152.  
  153. /* Used in THUNK_FOR_LOAD/STORE_INSN. */
  154.  
  155. static rtx check_insn;
  156.  
  157.  
  158. /* Number of uneventful instructions since the last eventful one. */
  159.  
  160. static int num_uneventful_insn = 0;
  161.  
  162.  
  163. /* Non-zero when outputing instructions to record event. */
  164.  
  165. static int issuing_event = 0;
  166.  
  167.  
  168. /* Non-zero when processing rtx CALL insn. */
  169.  
  170. static int in_rtx_call_insn = 0;
  171.  
  172.  
  173. /* rtx code for register containing pointer to AE buffer */
  174.  
  175. static rtx ae_buffer_pointer = NULL;
  176.  
  177.  
  178. /* rtx code for register containing pointer to end of AE buffer */
  179.  
  180. #if (defined (AE_BUFFER_BOUND_REG) || defined (AE_BUFFER_BOUND_VAR))
  181. static rtx ae_buffer_end_pointer = NULL;
  182. #endif
  183.  
  184.  
  185. /* Non-zero means last branch instruction was annuled and so did not
  186.    execute its delay slots. */
  187.  
  188. #if (defined (JUMP_DELAY_SLOTS) || defined (CJUMP_DELAY_SLOTS))
  189. static int annuled_branch_seen = 0;
  190. #endif
  191.  
  192.  
  193. /* Amount of space left in the AE buffer from the amount available
  194. upon block entry. */
  195.  
  196. static int space_left_in_chunk = 0;
  197.  
  198.  
  199.  
  200. /* Invoke just before assembly code for an instruction or label is
  201.    output.  Notice interesting events and issue a schema command and/or
  202.    produce code to record the event. */
  203.  
  204. void
  205. watch_insn_output (insn)
  206.      register rtx insn;
  207. {
  208.   rtx par_1;
  209.   register int i;
  210.  
  211.   if (GET_CODE (insn) == INSN
  212.       && GET_CODE (PATTERN (insn)) == PARALLEL
  213.       && (par_1 = XVECEXP (PATTERN (insn), 0, 0))
  214.       && ! (GET_CODE (par_1) == SET
  215.         || GET_CODE (par_1) == USE
  216.         || GET_CODE (par_1) == CLOBBER
  217.         || GET_CODE (par_1) == CALL
  218.         || GET_CODE (par_1) == RETURN))
  219.     /* Instruction munged by peephole optimization.  We don't have a
  220.        real pattern that we can interpret and the following instruction
  221.        is deleted.  Luckily, we record the patterns of instructions
  222.        ahead of the current instruction. */
  223.     {
  224.       rtx next_insn = next_insn_or_label (insn, 1);
  225.       register int i, num_examined = 0;
  226.  
  227.       while (la_t != la_h && la_insn [la_h] != next_insn)
  228.     {
  229.       /* Examine effects of instructions up to next (undeleted)
  230.          instruction. */
  231.       if (la_insn [la_h])
  232.         record_insn_effects (la_insn [la_h], la_pattern [la_h]);
  233.       la_h = (la_h + 1) % MAX_PEEP;
  234.       num_examined += 1;
  235.     }
  236.       /* Record instructions MAX_PEEP ahead for this instruction
  237.      (minus 1 for deleted next instruction) and deleted instructions. */
  238.       for (i = 0; i < num_examined; i ++)
  239.     peek_ahead (next_insn_or_label (insn, MAX_PEEP - 1 + i));
  240.     }
  241.   else
  242.     {
  243.       peek_ahead (next_insn_or_label (insn, MAX_PEEP));
  244.       record_insn_effects (insn, PATTERN (insn));
  245.     }
  246. }
  247.  
  248.  
  249. /* Initialize the look ahead buffer by filling it with the first instructions
  250.    in a function. */
  251.  
  252. void
  253. initialize_look_ahead_buffer ()
  254. {
  255.   register int i;
  256.  
  257.   la_h = la_t = 0;
  258.   if (n_basic_blocks > 0)
  259.     for (i = 0; i < MAX_PEEP; i++)
  260.       peek_ahead (insn_or_label (basic_block_head [0], i + 1));
  261. }
  262.  
  263.  
  264. /* Remember the instruction MAX_PEEP instructions further along, so
  265.    that we can find its pattern even if it is destroyed by peephole
  266.    optimization. */
  267.  
  268. static void
  269. peek_ahead (nth_insn)
  270.      rtx nth_insn;
  271. {
  272.   la_t = (la_t + 1) % MAX_PEEP;
  273.   if (la_t == la_h) la_h = (la_h + 1) % MAX_PEEP;
  274.   la_insn [la_t] = nth_insn;
  275.   la_pattern [la_t] = (nth_insn == (rtx) NULL
  276.                || GET_CODE (nth_insn) == CODE_LABEL
  277.                ? NULL : PATTERN (nth_insn));
  278. }
  279.  
  280.  
  281. /* Capture the an instruction's events by either producing a schema or
  282.    adding code to the assembly file to record values or both.  We
  283.    maintain an one instruction look-ahead buffer so that routines for
  284.    each type of instruction can be invoked before and after the assembly
  285.    code for the instruction is produced. */
  286.  
  287. void
  288. record_insn_effects (insn, pattern)
  289.      register rtx insn, pattern;
  290. {
  291.   static rtx prev_insn = NULL;
  292.   static rtx prev_pattern = NULL;
  293.  
  294.   if (prev_insn)
  295.     process_insn_after (prev_insn, prev_pattern);
  296.   if (insn)
  297.     process_insn_before (insn, pattern);
  298.   prev_insn = insn;
  299.   prev_pattern = pattern;
  300. }
  301.  
  302.  
  303. /* Invoke the appropriate routine for each type of instruction BEFORE its
  304.    assembly code is written to the file. */
  305.  
  306. static void
  307. process_insn_before (insn, pattern)
  308.      rtx insn, pattern;
  309. {
  310.   register aux_insn_info *info = &insn_info [INSN_UID (insn)];
  311.   register int flags = info->flags;
  312.   void thunk_for_load_insn ();
  313.  
  314.   store_dest = NULL;
  315.   /* Function start is processed before any instructions.  Block start
  316.      is process before instructions, but after labels. */
  317.   if (flags & FUNCTION_START_FLAG)
  318.     ae_function_start ();
  319.  
  320.   if ((flags & BLOCK_START_FLAG) && GET_CODE (insn) != CODE_LABEL)
  321.     process_block_start (insn);
  322.  
  323.   if (GET_CODE (insn) == CODE_LABEL)
  324.     ;
  325.   else if (flags & (EASY_INSN_FLAG | HARD_INSN_FLAG))
  326.     ae_before_easy_insn (insn, pattern);
  327.   else if (GET_CODE (insn) == CALL_INSN)
  328.     {
  329.       ae_before_call_insn (insn, flags & IMPOSSIBLE_INSN_FLAG);
  330.       if (flags & IMPOSSIBLE_INSN_FLAG)
  331.     note_stores (pattern, save_store_dest);
  332.       goto may_be_impossible;
  333.     }
  334.   else                /* Load and stores */
  335.     {
  336.       note_stores (pattern, save_store_dest);
  337.  
  338.       if (store_dest
  339.       && (GET_CODE (store_dest) == MEM
  340.           || GET_CODE (store_dest) == CONST))
  341.     ae_before_store_insn (insn, store_dest);
  342.       else
  343.     {
  344.       check_insn = insn;
  345.       before_insn_flg = 1;
  346.       if (GET_CODE (pattern) == SET)
  347.         /* Only interested in loads at this point. */
  348.         find_mem_refs (SET_SRC (pattern), thunk_for_load_insn);
  349.       else
  350.         APPLY_TO_EXP_IN_INSN (pattern,
  351.                   e,
  352.                   find_mem_refs (e, thunk_for_load_insn));
  353.  
  354.     may_be_impossible:
  355.       if (flags & IMPOSSIBLE_INSN_FLAG)
  356.         ae_before_impossible_insn (insn, store_dest);
  357.     }
  358.     }
  359.  
  360.   if (flags & BLOCK_END_FLAG)
  361.     ae_before_block_end (insn, block_no);
  362. }
  363.  
  364.  
  365. void
  366. process_block_start (insn)
  367. rtx insn;
  368. {
  369.   block_no = head_to_block_number (find_block_head (insn));
  370.   ae_block_start (insn, block_no,
  371.           cjump_target_p (basic_block_head [block_no]));
  372. }
  373.  
  374.  
  375. /* Invoke the appropriate routine for each type of instruction AFTER its
  376.    assembly code is written to the file. */
  377.  
  378. static void
  379. process_insn_after (insn, pattern)
  380.      rtx insn, pattern;
  381. {
  382.   register aux_insn_info *info = &insn_info [INSN_UID (insn)];
  383.   register int flags = info->flags;
  384.   void thunk_for_load_insn ();
  385.  
  386.   if ((flags & BLOCK_START_FLAG) && GET_CODE (insn) == CODE_LABEL)
  387.     process_block_start (insn);
  388.  
  389.   if (GET_CODE (insn) == CODE_LABEL)
  390.     ;
  391.   else if (flags & (EASY_INSN_FLAG | HARD_INSN_FLAG))
  392.     ae_after_easy_insn (insn, pattern);
  393.   else if (GET_CODE (insn) == CALL_INSN)
  394.     {
  395.       ae_after_call_insn (insn, flags & IMPOSSIBLE_INSN_FLAG);
  396.       if (flags & IMPOSSIBLE_INSN_FLAG)
  397.     note_stores (pattern, save_store_dest);
  398.       goto may_be_impossible;
  399.     }
  400.   else                /* Load and stores */
  401.     {
  402.       store_dest = NULL;
  403.       note_stores (pattern, save_store_dest);
  404.  
  405.       if (store_dest
  406.       && (GET_CODE (store_dest) == MEM || GET_CODE (store_dest) == CONST))
  407.     ae_after_store_insn (insn, store_dest);
  408.       else
  409.     {
  410.       check_insn = insn;
  411.       before_insn_flg = 0;
  412.       if (GET_CODE (pattern) == SET)
  413.         /* Only interested in loads at this point. */
  414.         find_mem_refs (SET_SRC (pattern), thunk_for_load_insn);
  415.       else
  416.         APPLY_TO_EXP_IN_INSN (pattern,
  417.                   e,
  418.                   find_mem_refs (e, thunk_for_load_insn));
  419.  
  420.     may_be_impossible:
  421.       if (flags & IMPOSSIBLE_INSN_FLAG)
  422.         ae_after_impossible_insn (insn, store_dest);
  423.     }
  424.     }
  425.  
  426.   if (flags & BLOCK_END_FLAG)
  427.     ae_after_block_end (insn, block_no);
  428. }
  429.  
  430.  
  431. /* Set STORE_DEST to the destination of a store instruction. */
  432.  
  433. static void
  434. save_store_dest (d, x) rtx d, x; {store_dest = d;}
  435.  
  436.  
  437. static void
  438. thunk_for_load_insn (exp, base, offset)
  439.      rtx exp, base, offset;
  440. {
  441.    if (before_insn_flg)
  442.      ae_before_load_insn (check_insn, exp);
  443.    else
  444.      ae_after_load_insn (check_insn, exp);
  445. }
  446.  
  447.  
  448. /* Return 1 if function contains an implicit final block and 0
  449.    otherwise. */
  450.  
  451. int
  452. implicit_last_block ()
  453. {
  454.   int l = n_basic_blocks - 1;
  455.  
  456.   if (l > 0)
  457.     {
  458.       rtx last_end = basic_block_end [l];
  459.       if (GET_CODE (last_end) == JUMP_INSN
  460.       && !simplejump_p (last_end)
  461.       && condjump_p (last_end))
  462.     return 1;
  463.       else
  464.     return 0;
  465.     }
  466.   return 0;
  467. }
  468.  
  469.  
  470.  
  471. /* Table of instructions that take up more than one word.  These are
  472.    usually pseudo-instructions allowed by the assembler.  Even elements
  473.    are instructions' names.  Odd elements are the size (in number of
  474.    words).  All other instructions are assumed to be STD_ASM_INSN_LENGTH
  475.    bytes.  Table must be sorted by instruction name. */
  476.  
  477. static char *asm_insn_size_tbl [] = {
  478. #ifdef ASM_INSN_SIZE_EXCEPTIONS
  479.   ASM_INSN_SIZE_EXCEPTIONS
  480. #else
  481.   0
  482. #endif
  483. };
  484.  
  485.  
  486. /* Invoked by OUTPUT_ASM_INSN before each instruction or label is
  487.    written to assembly file. */
  488.  
  489. void
  490. watch_asm_insn_output (template, operands)
  491.      register char *template;
  492.      rtx *operands;
  493. {
  494.   register char *e;
  495.  
  496. #if (defined (JUMP_DELAY_SLOTS) || defined (CJUMP_DELAY_SLOTS))
  497.   annuled_branch_seen = 0;
  498. #endif
  499.  
  500.   if (!issuing_event)
  501.     while (*template != '\0')
  502.       {
  503.     /* Skip white space */
  504.     while (*template == ' ' || *template == '\t') template ++;
  505.     if ((*template == ASM_COMMENT_CHAR))
  506.       ;
  507.     else if ((*template == ASM_DIRECTIVE_CHAR))
  508.       ;
  509.     else if (!in_rtx_call_insn && (e = ASM_INSN_IS_CALL (template)))
  510.       {
  511.         /* Instruction contains a call to a subroutine (whose name
  512.            probably begins with a ".") that is not apparent in rtx code. */
  513.  
  514.         register char buf [256], *p;
  515.  
  516.         flush_uneventful_insn (0);
  517.         /* Find end of subroutine name: */
  518.         for (p = e; *p != ',' && *p != ' ' && *p != '\n' && *p != '\0'; )
  519.           p ++;
  520.         buf [0] = '*';    /* Do not prepend an '_' */
  521.         strncpy (buf + 1, e, p - e);
  522.         buf [p - e + 1] = '\0';
  523.         call_schema_str (buf);
  524.       }
  525.     else
  526.       {
  527. #if (defined (JUMP_DELAY_SLOTS) || defined (CJUMP_DELAY_SLOTS))
  528.         if (BRANCH_IS_ANNULED (template))
  529.           annuled_branch_seen = 1;
  530. #endif
  531.         num_uneventful_insn += asm_insn_size (template);
  532.       }
  533.  
  534.     /* Check for multiple instructions in one string. */
  535.     while (*template != '\0' && *template != '\n') template ++;
  536.     if (*template == '\n') template ++;
  537.       }
  538. }
  539.  
  540.  
  541. static int
  542. asm_insn_size (template)
  543.   register char *template;
  544. {
  545. #ifdef ASM_INSN_SIZE_EXCEPTIONS
  546.   register int low = 0;
  547.   register int hi = ((sizeof (asm_insn_size_tbl) / sizeof (char *)) / 2) - 1;
  548.  
  549.   while (low <= hi)
  550.     {
  551.       register int mid = (low + hi) / 2;
  552.       register char *t = template, *p = asm_insn_size_tbl [2 * mid];
  553.  
  554.       while (*t == *p) {t++; p++;}
  555.  
  556.       if (*p == '\0')        /* End of pattern */
  557.     return (int) asm_insn_size_tbl [2 * mid + 1];
  558.       else if (*t > *p)
  559.     low = mid + 1;
  560.       else
  561.     hi = mid - 1;
  562.     }
  563. #endif
  564.  
  565.   return 1;            /* Most instructions are 1 word long */
  566. }
  567.  
  568.  
  569. /* Return non-zero if S2 is a substring of S1. */
  570.  
  571. static int
  572. substring (s1, s2)
  573.      register char *s1, *s2;
  574. {
  575.   for ( ; *s1 != '\0'; s1 ++)
  576.     {
  577.       register char *ss1 = s1, *ss2 = s2;
  578.  
  579.       for ( ; *ss1 && *ss2 && *ss1 == *ss2; ss1 ++, ss2 ++ );
  580.       if (*ss2 == '\0') return 1;
  581.     }
  582.   return 0;
  583. }
  584.  
  585.  
  586.  
  587. void
  588. ae_function_start ()
  589. {
  590.   function_start_schema (fun_name, n_basic_blocks + implicit_last_block ());
  591.   ae_buffer_pointer = MAKE_AE_BUFFER_POINTER ();
  592. #if (defined (AE_BUFFER_BOUND_REG) || defined (AE_BUFFER_BOUND_VAR))
  593.   ae_buffer_end_pointer = MAKE_AE_BOUND_POINTER ();
  594. #endif
  595.   SCHEMA_PROLOGUE (record_reg_on_entry);
  596. }
  597.  
  598.  
  599. static int
  600. record_sp ()
  601. {
  602.   unknown_def_schema (STACK_POINTER_REGNUM);
  603.   issue_event (stack_pointer_rtx);
  604.   return 1;
  605. }
  606.  
  607.  
  608. static int
  609. record_fp ()
  610. {
  611.   unknown_def_schema (FRAME_POINTER_REGNUM);
  612.   issue_event (frame_pointer_rtx);
  613.   return 1;
  614. }
  615.  
  616.  
  617. void
  618. ae_function_end ()
  619. {
  620.   SCHEMA_EPILOGUE ();
  621.   function_end_schema (fun_name);
  622. }
  623.  
  624.  
  625.  
  626. /* If a conditional jumps to a block, then issue an event upon entry. */
  627.  
  628. void
  629. ae_block_start (insn, block_no, cjump_target_p)
  630. rtx insn;
  631. int block_no, cjump_target_p;
  632. {
  633.   space_left_in_chunk = 0;
  634.   flush_uneventful_insn (0);    /* Previous block's delayed instruction */
  635.   if (cjump_target_p)
  636.     {
  637.       block_start_schema (block_no, 1);
  638.       /* Plus 1 since function m */
  639.       issue_short_event (block_no, n_basic_blocks + implicit_last_block ());
  640.     }
  641.   else
  642.     block_start_schema (block_no, 0);
  643. }
  644.  
  645.  
  646. void
  647. ae_before_block_end (insn, block_no)
  648. rtx insn;
  649. int block_no;
  650. {
  651. }
  652.  
  653.  
  654. void
  655. ae_after_block_end (insn, block_no)
  656. rtx insn;
  657. int block_no;
  658. {
  659.   if (insn == NULL)
  660.     {
  661.       flush_uneventful_insn (0);
  662.       block_end_schema (insn, block_no, 0);
  663.     }
  664.   else if (GET_CODE (insn) == JUMP_INSN)
  665.     {
  666.       if (simplejump_p (insn))
  667.     {
  668. #ifdef JUMP_DELAY_SLOTS
  669.       if (annuled_branch_seen)
  670.         flush_uneventful_insn (1);
  671.       else
  672.         {
  673.           flush_uneventful_insn (1 + JUMP_DELAY_SLOTS);
  674.           num_uneventful_insn += JUMP_DELAY_SLOTS;
  675.         }
  676. #else
  677.       flush_uneventful_insn (1);
  678. #endif
  679.       block_end_jump_schema (insn,
  680.                  block_no,
  681.                  head_to_block_number (JUMP_LABEL (insn)),
  682.                  cjump_target_p (JUMP_LABEL (insn)));
  683.     }
  684.       else if (condjump_p (insn) || multiway_jump_p (insn))
  685.     {
  686. #ifdef CJUMP_DELAY_SLOTS
  687.       flush_uneventful_insn (1 + CJUMP_DELAY_SLOTS);
  688.       num_uneventful_insn += 1;
  689. #else
  690.       flush_uneventful_insn (1);
  691. #endif
  692.       block_end_cjump_schema (insn, block_no);
  693.     }
  694.       else
  695.     {
  696.       /* A multiway branch appears as:
  697.          (jump_insn (parallel [(set (pc) (reg #)) (use (label_ref ##))]))
  698.          where ## is the label of the instruction containing the address
  699.          vector (which is not passed to us by final).  Process the address
  700.          vector, no this blind jump. */
  701.       ae_after_block_end (NEXT_INSN (NEXT_INSN
  702.                      (CONTAINING_INSN
  703.                       (XEXP (XVECEXP (PATTERN (insn),
  704.                               0, 1),
  705.                          0)))),
  706.                   block_no);
  707.     }
  708.     }
  709.   else
  710.     {
  711.       flush_uneventful_insn (0);
  712.       /* Block ends with non-jump instruction. */
  713.       block_end_schema (insn,
  714.             block_no,
  715.             cjump_target_p (next_insn_or_label (insn, 1)));
  716.     }
  717. }
  718.  
  719.  
  720. static void
  721. ae_before_call_insn (insn, impossible_flag)
  722.      rtx insn;
  723.      int impossible_flag;
  724. {
  725.   in_rtx_call_insn = 1;
  726. }
  727.  
  728.  
  729. static void
  730. ae_after_call_insn (insn, impossible_flag)
  731.      rtx insn;
  732.      int impossible_flag;
  733. {
  734.   rtx p = PATTERN (insn);
  735.   rtx x = (GET_CODE (p) == PARALLEL ? XVECEXP (p, 0, 0) : p);
  736.   rtx c = (GET_CODE (x) == SET ? SET_SRC (x) : x);
  737.   rtx callee = XEXP (c, 0);
  738.  
  739. #ifdef CALL_DELAY_SLOTS
  740.   flush_uneventful_insn (1 + CALL_DELAY_SLOTS);
  741.   if (impossible_flag)
  742.     num_uneventful_insn += 2;    /* To account for NOP before call is output */
  743.   else
  744.     num_uneventful_insn += 1;    /* To account for NOP */
  745. #else
  746.   flush_uneventful_insn (1);
  747. #endif
  748.   in_rtx_call_insn = 0;
  749.   if (GET_CODE (callee) == MEM && GET_CODE (XEXP (callee, 0)) == SYMBOL_REF)
  750.     call_schema (XEXP (callee, 0));
  751.   else if (GET_CODE (callee) == MEM && GET_CODE (XEXP (callee, 0)) == REG)
  752.     {
  753.       list defs = defns_reaching_insn (insn, XEXP (callee, 0));
  754.  
  755.       if (defs != NULL && CDR (defs) == NULL) /* 1 element list */
  756.     {
  757.       rtx def = PATTERN ((rtx) CAR (defs));
  758.  
  759.       if (GET_CODE (def) == SET && GET_CODE (SET_SRC (def)) == SYMBOL_REF)
  760.         call_schema (SET_SRC (def));
  761.       else
  762.         goto indirect_call;
  763.     }
  764.       else
  765.     /* Otherwise, do an indirect call to an address that is saved (since
  766.        the instruction appears to be impossible). */
  767.       indirect_call:
  768.     call_indirect_schema (XEXP (callee, 0));
  769.       free_list (defs);
  770.     }
  771.   else
  772.     error ("Unknown quantity to call_indirect");
  773. }
  774.  
  775.  
  776. static void
  777. ae_before_easy_insn (insn, pattern)
  778.      rtx insn, pattern;
  779. {
  780. }
  781.  
  782.  
  783. static void
  784. ae_after_easy_insn (insn, pattern)
  785.      rtx insn, pattern;
  786. {
  787.   flush_uneventful_insn (1);
  788.   if (GET_CODE (pattern) == SET)
  789.     {
  790.       register rtx d = SET_DEST (pattern);
  791.       register rtx e = SET_SRC (pattern);
  792.  
  793.       while (1)
  794.     switch (GET_CODE (e))
  795.       {
  796.       case PLUS:
  797.       case MINUS:
  798.       case MULT:
  799.       case DIV:
  800.       case MOD:
  801.       case AND:
  802.       case IOR:
  803.       case LSHIFT:
  804.       case ASHIFT:
  805.       case LSHIFTRT:
  806.         compute_def_schema (REGNO (d), GET_CODE (e), XEXP (e, 0),
  807.                 XEXP (e, 1));
  808.         return;
  809.  
  810.       case NEG:
  811.       case NOT:
  812.         compute_def_schema (REGNO (d), GET_CODE (e), XEXP (e, 0), NULL);
  813.         return;
  814.  
  815.       case SYMBOL_REF:
  816.         if (*XSTR (e, 0) == '*')
  817.           /* Probably a local symbol, so record value */
  818.           {
  819.         unknown_def_schema (REGNO (d));
  820.         issue_event (d);
  821.           }
  822.         else
  823.           symbol_def_schema (REGNO (d), XSTR (e, 0), 0);
  824.         return;
  825.  
  826.       case SIGN_EXTEND:
  827.         e = XEXP (e, 0);
  828.         break;
  829.  
  830.       case CONST:
  831.         {
  832.           /* Instruction is: rx <- @sym or rx <- @sym + c. */
  833.           rtx t = XEXP (e, 0);
  834.           rtx base, offset;
  835.  
  836.           if (GET_CODE (t) == PLUS)
  837.         {
  838.           base = XEXP (t, 0), offset = XEXP (t, 1);
  839.           if (GET_CODE (base) == SYMBOL_REF
  840.               && GET_CODE (offset) == CONST_INT)
  841.             {
  842.               char *symbol_name = XSTR (base, 0);
  843.  
  844.               if (*symbol_name == '*')
  845.             {
  846.               unknown_def_schema (REGNO (d));
  847.               issue_event (d);
  848.             }
  849.               else
  850.             symbol_def_schema (REGNO (d), symbol_name,
  851.                        XINT (offset, 0));
  852.             }
  853.           else
  854.             goto unknown;
  855.         }
  856.           else if (GET_CODE (t) == SYMBOL_REF)
  857.         symbol_def_schema (REGNO (d), XEXP (t, 0), 0);
  858.           else
  859.         goto unknown;
  860.           return;
  861.         }
  862.  
  863.       case SUBREG:
  864.         d = SUBREG_REG (d);
  865.         /* Fall through */
  866.  
  867.       case CONST_INT:
  868.       case REG:
  869.         compute_def_schema (REGNO (d), NIL, e, NULL);
  870.         return;
  871.  
  872.       case LABEL_REF:
  873.         unknown_def_schema (REGNO (d));
  874.         issue_event (d);
  875.         return;
  876.  
  877.       default:
  878.         goto unknown;
  879.       }
  880.     }
  881.   else if (GET_CODE (pattern) == PARALLEL)
  882.     {
  883.       register int i;
  884.  
  885.       for (i = 0; i < XVECLEN (pattern, 0); i ++)
  886.     ae_before_easy_insn (insn, XVECEXP (pattern, 0, i));
  887.     }
  888.   else
  889.     {
  890.     unknown:
  891.       print_rtl(stderr, insn);
  892.       error ("Easy insn wasn't so easy."); /*NOTREACHED*/
  893.     }
  894. }
  895.  
  896.  
  897.  
  898. void
  899. ae_before_impossible_insn (insn, store_dest)
  900.      rtx insn, store_dest;
  901. {
  902. }
  903.  
  904.  
  905. void
  906. ae_after_impossible_insn (insn, store_dest)
  907.      rtx insn, store_dest;
  908. {
  909.   flush_uneventful_insn (1);
  910.   unknown_def_schema (REGNO (store_dest));
  911.   issue_event (store_dest);
  912. }
  913.  
  914.  
  915. void
  916. ae_before_load_insn (insn, exp)
  917.      rtx insn, exp;
  918. {
  919.   void thunk_for_load_before ();
  920.  
  921.   find_mem_refs (exp, thunk_for_load_before);
  922. }
  923.  
  924.  
  925. void
  926. ae_after_load_insn (insn, exp)
  927.      rtx insn, exp;
  928. {
  929.   void thunk_for_load_after ();
  930.  
  931.   flush_uneventful_insn (1);
  932.   find_mem_refs (exp, thunk_for_load_after);
  933. }
  934.  
  935.  
  936. static void
  937. thunk_for_load_before (exp, base, offset)
  938.      rtx exp, base, offset;
  939. {
  940.   if (GET_CODE (base) == SYMBOL_REF)
  941.     {
  942.       if (*XSTR (base, 0) == '*')
  943.     goto unknown;        /* Probably a local symbol, so record value */
  944.       else if (offset == NULL)
  945.     ;
  946.       else if (GET_CODE (offset) == CONST_INT)
  947.     ;
  948.       else
  949.     goto unknown;
  950.     }
  951.   else if (REG_P (base))
  952.     {
  953.       if (offset == NULL)
  954.     ;
  955.       else if (GET_CODE (offset) == CONST_INT)
  956.     ;
  957.       else if (REG_P (offset))
  958.     ;
  959.       else
  960.     goto unknown;
  961.     }
  962.   else if (GET_CODE (base) == CONST
  963.        && GET_CODE (XEXP (base, 0)) == PLUS
  964.        && GET_CODE (XEXP (XEXP (base, 0), 0)) == SYMBOL_REF)
  965.     {
  966.       if (*XSTR (base, 0) == '*')
  967.     goto unknown;        /* Probably a local symbol, so record value */
  968.     }
  969.   else
  970.     {
  971.     unknown:
  972.       issue_address_event (exp, base, offset);
  973.     }
  974. }
  975.  
  976.  
  977. static void
  978. thunk_for_load_after (exp, base, offset)
  979.      rtx exp, base, offset;
  980. {
  981.   if (GET_CODE (base) == SYMBOL_REF)
  982.     {
  983.       char *symbol_name = XSTR (base, 0);
  984.  
  985.       if (*symbol_name == '*')
  986.     goto unknown;        /* Probably a local symbol, so record value */
  987.       else if (offset == NULL)
  988.     load_symbol_schema (symbol_name, 0);
  989.       else if (GET_CODE (offset) == CONST_INT)
  990.     load_symbol_schema (symbol_name, XINT (offset, 0));
  991.       else
  992.     goto unknown;
  993.     }
  994.   else if (REG_P (base))
  995.     {
  996.       if (offset == NULL)
  997.     load_schema_int_offset (REGNO (base), 0, 0);
  998.       else if (GET_CODE (offset) == CONST_INT)
  999.     load_schema_int_offset (REGNO (base), XINT (offset, 0), 0);
  1000.       else if (REG_P (offset))
  1001.     load_schema_reg_offset (REGNO (base), offset, 0);
  1002.       else
  1003.     goto unknown;
  1004.     }
  1005.   else if (GET_CODE (base) == CONST
  1006.        && GET_CODE (XEXP (base, 0)) == PLUS
  1007.        && GET_CODE (XEXP (XEXP (base, 0), 0)) == SYMBOL_REF)
  1008.     {
  1009.       char *symbol_name = XSTR (XEXP (XEXP (base, 0), 0), 0);
  1010.       if (*symbol_name == '*')
  1011.     goto unknown;        /* Probably a local symbol, so record value */
  1012.       else
  1013.     load_symbol_schema (symbol_name, XINT (XEXP (XEXP (base, 0), 1), 0));
  1014.     }
  1015.   else
  1016.     {
  1017.     unknown:
  1018.       load_unknown_schema ();
  1019.     }
  1020. }
  1021.  
  1022.  
  1023. void
  1024. ae_before_store_insn (insn, store_dest)
  1025.      rtx insn, store_dest;
  1026. {
  1027.   void thunk_for_store_before ();
  1028.  
  1029.   find_mem_refs (store_dest, thunk_for_store_before);
  1030. }
  1031.  
  1032.  
  1033. void
  1034. ae_after_store_insn (insn, store_dest)
  1035.      rtx insn, store_dest;
  1036. {
  1037.   void thunk_for_store_after ();
  1038.  
  1039.   flush_uneventful_insn (1);
  1040.   find_mem_refs (store_dest, thunk_for_store_after);
  1041. }
  1042.  
  1043.  
  1044. static void
  1045. thunk_for_store_before (exp, base, offset)
  1046.      rtx exp, base, offset;
  1047. {
  1048.   if (GET_CODE (base) == SYMBOL_REF)
  1049.     {
  1050.       if (*XSTR (base, 0) == '*')
  1051.     goto unknown;        /* Probably a local symbol, so record value */
  1052.       else if (offset == NULL)
  1053.     ;
  1054.       else if (GET_CODE (offset) == CONST_INT)
  1055.     ;
  1056.       else
  1057.     goto unknown;
  1058.     }
  1059.   else if (REG_P (base))
  1060.     {
  1061.       if (offset == NULL)
  1062.     ;
  1063.       else if (GET_CODE (offset) == CONST_INT)
  1064.     ;
  1065.       else if (REG_P (offset))
  1066.     ;
  1067.       else
  1068.     goto unknown;
  1069.     }
  1070.   else if (GET_CODE (base) == CONST
  1071.        && GET_CODE (XEXP (base, 0)) == PLUS
  1072.        && GET_CODE (XEXP (XEXP (base, 0), 0)) == SYMBOL_REF)
  1073.     {
  1074.       if (*XSTR (base, 0) == '*')
  1075.     goto unknown;        /* Probably a local symbol, so record value */
  1076.     }
  1077.   else
  1078.     {
  1079.     unknown:
  1080.       issue_address_event (exp, base, offset);
  1081.     }
  1082. }
  1083.  
  1084.  
  1085. static void
  1086. thunk_for_store_after (exp, base, offset)
  1087.      rtx exp, base, offset;
  1088. {
  1089.   if (GET_CODE (base) == SYMBOL_REF)
  1090.     {
  1091.       char *symbol_name = XSTR (base, 0);
  1092.  
  1093.       if (*symbol_name == '*')
  1094.     goto unknown;        /* Probably a local symbol, so record value */
  1095.       else if (offset == NULL)
  1096.     store_symbol_schema (symbol_name, 0);
  1097.       else if (GET_CODE (offset) == CONST_INT)
  1098.     store_symbol_schema (symbol_name, XINT (offset, 0));
  1099.       else
  1100.     goto unknown;
  1101.     }
  1102.   else if (REG_P (base))
  1103.     {
  1104.       if (offset == NULL)
  1105.     store_schema_int_offset (REGNO (base), 0, 0);
  1106.       else if (GET_CODE (offset) == CONST_INT)
  1107.     store_schema_int_offset (REGNO (base), XINT (offset, 0), 0);
  1108.       else if (REG_P (offset))
  1109.     store_schema_reg_offset (REGNO (base), offset, 0);
  1110.       else
  1111.     goto unknown;
  1112.     }
  1113.   else if (GET_CODE (base) == CONST
  1114.        && GET_CODE (XEXP (base, 0)) == PLUS
  1115.        && GET_CODE (XEXP (XEXP (base, 0), 0)) == SYMBOL_REF)
  1116.     {
  1117.       char *symbol_name = XSTR (XEXP (XEXP (base, 0), 0), 0);
  1118.  
  1119.       if (*symbol_name == '*')
  1120.     goto unknown;
  1121.       else
  1122.     store_symbol_schema (symbol_name, XINT (XEXP (XEXP (base, 0), 1), 0));
  1123.     }
  1124.   else
  1125.     {
  1126.     unknown:
  1127.       store_unknown_schema ();
  1128.     }
  1129. }
  1130.  
  1131.  
  1132. static void
  1133. flush_uneventful_insn (num_current)
  1134.      int num_current;
  1135. {
  1136.   if (num_uneventful_insn - num_current > 0)
  1137.     uneventful_schema (num_uneventful_insn - num_current, STD_ASM_INSN_LENGTH);
  1138.   num_uneventful_insn = 0;
  1139. }
  1140.  
  1141.  
  1142.  
  1143. /* Issue a schema by writing to the schema file. */
  1144.  
  1145.  
  1146. static void
  1147. function_start_schema (fun_name, n_blocks)
  1148.      char *fun_name;
  1149.      int n_blocks;
  1150. {
  1151.   fprintf (schema_out_file, "%s ", FUNCTION_START);
  1152.   assemble_name (schema_out_file, fun_name);
  1153.   fprintf (schema_out_file, " %d\n", n_blocks);
  1154. }
  1155.  
  1156.  
  1157. static void
  1158. function_end_schema (fun_name)
  1159.      char *fun_name;
  1160. {
  1161.   fprintf (schema_out_file, "%s ", FUNCTION_END);
  1162.   assemble_name (schema_out_file, fun_name);
  1163.   fprintf (schema_out_file, "\n\n");
  1164. }
  1165.  
  1166.  
  1167. static void
  1168. block_start_schema (block_no, target_p)
  1169.      int block_no, target_p;
  1170. {
  1171.   fprintf (schema_out_file, "\n%s %d\n",
  1172.        (target_p ? BLOCK_START_TARGET : BLOCK_START), block_no);
  1173. }
  1174.  
  1175.  
  1176. static void
  1177. block_end_schema (insn, block_no, next_target_p)
  1178.      rtx insn;
  1179.      int block_no, next_target_p;
  1180. {
  1181.   fprintf (schema_out_file, "%s %d",
  1182.        (next_target_p ? BLOCK_END_NEXT_TARGET : BLOCK_END), block_no);
  1183.   edge_schema (insn);
  1184. }
  1185.  
  1186.  
  1187. static void
  1188. block_end_jump_schema (insn, block_no, target_block_no, next_target_p)
  1189.      rtx insn;
  1190.      int block_no, target_block_no, next_target_p;
  1191. {
  1192.   fprintf (schema_out_file, "%s %d %d",
  1193.        (next_target_p ? BLOCK_END_JUMP_NEXT_TARGET : BLOCK_END_JUMP),
  1194.        block_no, target_block_no);
  1195.   edge_schema (insn);
  1196. }
  1197.  
  1198.  
  1199. static void
  1200. edge_schema (insn)
  1201.      rtx insn;
  1202. {
  1203.   if (insn != NULL)
  1204.     {
  1205.       /* List exit before backedges */
  1206.       DOLIST (e, list, insn_info [INSN_UID (insn)].exit_edge,
  1207.           {fprintf (schema_out_file, " %s(%d %d)",
  1208.             LOOP_EXIT, CAR (e), CDR(e));
  1209.            free (e);});
  1210.       DOLIST (e, list, insn_info [INSN_UID (insn)].back_edge,
  1211.           {fprintf (schema_out_file, " %s(%d %d)",
  1212.             LOOP_BACK, CAR (e), CDR (e));
  1213.            free (e);});
  1214.       DOLIST (e, list, insn_info [INSN_UID (insn)].entry_edge,
  1215.           {fprintf (schema_out_file, " %s(%d %d)",
  1216.             LOOP_ENTRY, CAR (e), CDR (e));
  1217.            free (e);});
  1218.     }
  1219.   fprintf (schema_out_file, "\n");
  1220. }
  1221.  
  1222.  
  1223. static void
  1224. block_end_cjump_schema (insn, block_no)
  1225.      rtx insn;
  1226.      int block_no;
  1227. {
  1228.   fprintf (schema_out_file, "%s %d", BLOCK_END_CJUMP, block_no);
  1229.   if (condjump_p (insn))
  1230.     fprintf (schema_out_file, " %d %d", block_no + 1,
  1231.          head_to_block_number (JUMP_LABEL (insn)));
  1232.   else
  1233.     {
  1234.       rtx body =  PATTERN (insn);
  1235.       register int vlen, i;
  1236.  
  1237.       vlen = XVECLEN (body, 0);
  1238.       for (i = 0; i < vlen; i++)
  1239.     fprintf (schema_out_file, " %d",
  1240.          head_to_block_number (XEXP (XVECEXP (body, 0, i), 0)));
  1241.     }
  1242.   edge_schema (insn);
  1243. }
  1244.  
  1245.  
  1246. static void
  1247. simple_def_schema (rd, r1, value)
  1248.      int rd, r1, value;
  1249. {
  1250.   fprintf (schema_out_file, "%s2 R%d #R%d + #I%d\n",
  1251.        COMPUTE_DEFN_, rd, r1, value);
  1252. }
  1253.  
  1254.  
  1255. static void
  1256. compute_def_schema (rd, code, a1, a2)
  1257.      int rd;
  1258.      RTX_CODE code;
  1259.      rtx a1, a2;
  1260. {
  1261.   if (code == NIL)        /* Nullary */
  1262.     {
  1263.       fprintf (schema_out_file, "%s0 R%d ", COMPUTE_DEFN_, rd);
  1264.       rtx_arg_out (schema_out_file, a1);
  1265.     }
  1266.   else if (a2 == NULL)        /* Unary */
  1267.     {
  1268.       fprintf (schema_out_file, "%s1 R%d %s ", COMPUTE_DEFN_, rd,
  1269.            rtx_op_out (code));
  1270.       rtx_arg_out (schema_out_file, a1);
  1271.     }
  1272.   else                /* Binary */
  1273.     {
  1274.       fprintf (schema_out_file, "%s2 R%d ", COMPUTE_DEFN_, rd);
  1275.       rtx_arg_out (schema_out_file, a1);
  1276.       fprintf (schema_out_file, " %s ", rtx_op_out (code));
  1277.       rtx_arg_out (schema_out_file, a2);
  1278.     }
  1279.   fprintf (schema_out_file, "\n");
  1280. }
  1281.  
  1282.  
  1283. static void
  1284. rtx_arg_out (file, a)
  1285.      FILE *file;
  1286.      rtx a;
  1287. {
  1288.   switch (GET_CODE (a))
  1289.     {
  1290.     case REG:
  1291.       fprintf (file, "#R%d", REGNO (a));
  1292.       break;
  1293.     case SUBREG:
  1294.       rtx_arg_out (file, SUBREG_REG (a));
  1295.       break;
  1296.     case CONST_INT:
  1297.       fprintf (file, "#I%d", INTVAL (a));
  1298.       break;
  1299.     case SYMBOL_REF:
  1300.       fprintf (file, "#S");
  1301.       assemble_name (file, XEXP (a, 0));
  1302.       break;
  1303.     default: error ("Unknown object to output"); /*NOTREACHED*/
  1304.     }
  1305. }
  1306.  
  1307.  
  1308. char *
  1309. rtx_op_out (code)
  1310.      RTX_CODE code;
  1311. {
  1312.   switch (code)
  1313.     {
  1314.     case PLUS: return "+";
  1315.     case MINUS: return "-";
  1316.     case MULT: return "*";
  1317.     case DIV: return "/";
  1318.     case MOD: return "%";
  1319.     case AND: return "&";
  1320.     case IOR: return "|";
  1321.     case LSHIFT: return "<<";
  1322.     case ASHIFT: return "<<";
  1323.     case LSHIFTRT: return ">>";
  1324.     case NEG: return "-";
  1325.     case NOT: return "~";
  1326.     default: error ("Unknown operator to output"); /*NOTREACHED*/
  1327.     }
  1328. }
  1329.  
  1330.  
  1331. static void
  1332. symbol_def_schema (rd, symbol, offset)
  1333.      int rd;
  1334.      char *symbol;
  1335.      int offset;
  1336. {
  1337.   fprintf (schema_out_file, "%s2 R%d #I%d + #S", COMPUTE_DEFN_, rd, offset);
  1338.   assemble_name (schema_out_file, symbol);
  1339.   fprintf (schema_out_file, "\n");
  1340. }
  1341.  
  1342.  
  1343. static void
  1344. unknown_def_schema (rd)
  1345.      int rd;
  1346. {fprintf (schema_out_file, "%s R%d\n", UNKNOWN_DEFN, rd);}
  1347.  
  1348.  
  1349. static void
  1350. store_schema_int_offset (reg_no, offset, double_p)
  1351.      int reg_no, offset, double_p;
  1352. {
  1353.   fprintf (schema_out_file, "%s #R%d + #I%d\n",
  1354.        (double_p ? STORE_D_INST : STORE_INST), reg_no, offset);
  1355. }
  1356.  
  1357.  
  1358. static void
  1359. store_schema_reg_offset (reg_no, offset_reg, double_p)
  1360.      int reg_no;
  1361.      rtx offset_reg;
  1362.      int double_p;
  1363. {
  1364.   fprintf (schema_out_file, "%s #R%d + #R%d\n",
  1365.        (double_p ? STORE_D_INST : STORE_INST), reg_no, REGNO (offset_reg));
  1366. }
  1367.  
  1368.  
  1369. static void
  1370. store_symbol_schema (symbol, offset)
  1371.      char *symbol;
  1372.      int offset;
  1373. {
  1374.   fprintf (schema_out_file, "%s #I%d + #S", STORE_INST, offset);
  1375.   assemble_name (schema_out_file, symbol);
  1376.   fprintf (schema_out_file, "\n");
  1377. }
  1378.  
  1379.  
  1380. static void
  1381. store_unknown_schema ()
  1382. {fprintf (schema_out_file, "%s\n", STORE_UNKNOWN_INST);}
  1383.  
  1384.  
  1385. static void
  1386. load_schema_int_offset (reg_no, offset, double_p)
  1387.      int reg_no, offset, double_p;
  1388. {
  1389.   fprintf (schema_out_file, "%s #R%d + #I%d\n",
  1390.        (double_p ? LOAD_D_INST : LOAD_INST), reg_no, offset);
  1391. }
  1392.  
  1393. static void
  1394. load_schema_reg_offset (reg_no, offset_reg, double_p)
  1395.      int reg_no;
  1396.      rtx offset_reg;
  1397.      int double_p;
  1398. {
  1399.   fprintf (schema_out_file, "%s #R%d + #R%d\n",
  1400.        (double_p ? LOAD_D_INST : LOAD_INST), reg_no, REGNO (offset_reg));
  1401. }
  1402.  
  1403.  
  1404. static void
  1405. load_symbol_schema (symbol, offset)
  1406.      char *symbol;
  1407.      int offset;
  1408. {
  1409.   fprintf (schema_out_file, "%s #I%d + #S", LOAD_INST, offset);
  1410.   assemble_name (schema_out_file, symbol);
  1411.   fprintf (schema_out_file, "\n");
  1412. }
  1413.  
  1414.  
  1415. static void
  1416. load_unknown_schema ()
  1417. {fprintf (schema_out_file, "%s\n", LOAD_UNKNOWN_INST);}
  1418.  
  1419.  
  1420. static void
  1421. call_schema (callee)
  1422.      rtx callee;
  1423. {call_schema_str (XSTR (callee, 0));}
  1424.  
  1425.  
  1426. static void
  1427. call_schema_str (callee)
  1428.      char *callee;
  1429. {
  1430.   fprintf (schema_out_file, "%s ", CALL_INST);
  1431.   assemble_name (schema_out_file, callee);
  1432.   fprintf (schema_out_file, "\n");
  1433. }
  1434.  
  1435.  
  1436. static void
  1437. call_indirect_schema (callee_reg)
  1438.      rtx callee_reg;
  1439. {
  1440.   fprintf (schema_out_file, "%s R%d\n", CALL_INDIRECT_INST,
  1441.        REGNO (callee_reg));
  1442. }
  1443.  
  1444.  
  1445. static void
  1446. uneventful_schema (num_insn, size_insn)
  1447.      int num_insn, size_insn;
  1448. {
  1449.   fprintf (schema_out_file, "%s %d %d\n", UNEVENTFUL_INST,
  1450.        num_insn, size_insn);
  1451. }
  1452.  
  1453.  
  1454.  
  1455. /* The instruction sequence to store a full-word event in the AE
  1456.    buffer looks like:
  1457.  
  1458.      CMP RB, RL
  1459.      BLE  OK                ! Check if buffer is full
  1460.      CALL AE_FLUSH_BUFFER
  1461.   OK:
  1462.  
  1463.      ST VALUE, 0 + RB            ! Store word.
  1464.      ADD RB, 4, RB            ! Bump pointer
  1465.  
  1466. RB is the register or variable containing a pointer to next free byte
  1467. in AE buffer.  RL can be a register or variable containing a pointer
  1468. to end of this buffer - CHUNK_SIZE.  Or, RL can be a constant value
  1469. (e.g., first negative number minus a small offset) pointing to the end
  1470. of this buffer.
  1471.  
  1472. We cheat a bit and only perform the space check on the first event in
  1473. a block.  At this test, we check for enough memory for all events in
  1474. the block.  However, when we see the first event, we don't know how
  1475. many more events will be in the block, so we check for a lot
  1476. (CHUNK_SIZE) of space.  If we overestimate the amount, it does not
  1477. matter since RB rarely is near the end of the buffer.
  1478.  
  1479. Also, on most machines, we cannot do a simple store of the value since
  1480. the buffer contains: unsigned chars, unsigned shorts, and longs and
  1481. hence is byte-aligned. */
  1482.  
  1483.  
  1484. /* Produce the space check at the beginning of a block. */
  1485.  
  1486. static void
  1487. issue_event_space_check (comment, size)
  1488.      char *comment;
  1489.      int size;
  1490. {
  1491.   char buffer[256];
  1492.  
  1493.   if (space_left_in_chunk > size)
  1494.     {
  1495.       sprintf (buffer, "\t\t\t%c %s Event", ASM_COMMENT_CHAR, comment);
  1496.       output_asm_insn (buffer, NULL);
  1497.       space_left_in_chunk -= size;
  1498.       return;
  1499.     }
  1500.   else
  1501.     {
  1502.       space_left_in_chunk = CHUNK_SIZE;
  1503.       GENERATE_SPACE_CHECK (comment, size);
  1504.     }
  1505. }
  1506.  
  1507.  
  1508. static void
  1509. issue_event (value)
  1510.      rtx value;
  1511. {
  1512.   issuing_event = 1;
  1513.   issue_event_space_check ("", 4);
  1514.   GENERATE_EVENT (value);
  1515.   issuing_event = 0;
  1516. }
  1517.  
  1518.  
  1519. static void
  1520. issue_short_event (value, max_value)
  1521.      int value, max_value;
  1522. {
  1523.   rtx xops [2];
  1524.   int bytes = (max_value < 256 ? 1 : 2);
  1525.  
  1526.   issuing_event = 1;
  1527.   issue_event_space_check ("Short", bytes);
  1528.   GENERATE_SHORT_EVENT (value, bytes);
  1529.   issuing_event = 0;
  1530. }
  1531.  
  1532.  
  1533. static void
  1534. issue_address_event (address, base, offset)
  1535.      rtx address, base, offset;
  1536. {
  1537.   issuing_event = 1;
  1538.   issue_event_space_check ("Address", 4);
  1539.   GENERATE_ADDRESS_EVENT(address, base, offset);
  1540.   issuing_event = 0;
  1541. }
  1542.